<?php

require_once '../simpletest/autorun.php';

require_once '../CryoBB/Base.php';
require_once '../CryoBB/Tag.php';
require_once '../CryoBB/Tag/Parameter.php';
require_once '../CryoBB/Strategy/Strict.php';
require_once '../CryoBB/Emoticons.php';
require_once '../CryoBB/Processor.php';
require_once '../CryoBB/Match.php';
require_once '../Demo/processors/Upper.php';

/*
 * @Todo
 * ----------------------------------------------------------------------------
 * Improve regular expressions
 * Create a hyperlinking function that turns non bb coded URLs into clickable 
 *    hyperlinks.
 * Better error reporting and verbosity
 * ----------------------------------------------------------------------------
 */
class TestOfBase extends UnitTestCase
{

	function testShouldLeaveUnrecognizedTag()
	{
		$base = new CryoBB_Base();
		
		$actual = $base->make('[b]123abc[/b]');
		$this->assertEqual($actual, '[b]123abc[/b]', 'When the user has not defined something as BBCode, should treat it as literal text');
	}
	
	function testShouldConvertBBCodeToHTML()
	{
		$base = new CryoBB_Base();
		$base->addTag($this->tagBold());
		
		$actual = $base->make('[b]123abc[/b]');
		$this->assertEqual($actual, '<strong>123abc</strong>', 'Should convert BBCode to HTML');
	}
	
	function testShouldConvertTwoBBCodeTags()
	{
		$base = new CryoBB_Base();
		$base->addTag($this->tagBold());
		$base->addTag($this->tagItalics());
		
		$actual = $base->make('[b]123abc[/b] [i]foo[/i]');
		$this->assertEqual($actual, '<strong>123abc</strong> <em>foo</em>', 'Should convert two BBCode tags to HTML');
	}
	
	function testShouldConvertTwoNestedBBCodeTags()
	{
		$base = new CryoBB_Base();
		$base->addTag($this->tagBold());
		$base->addTag($this->tagItalics());
		
		$actual = $base->make('[b]123abc [i]foo[/i][/b]');
		$this->assertEqual($actual, '<strong>123abc <em>foo</em></strong>', 'Should convert two nested BBCode tags to nested HTML');
	}
	
//	function testShouldGenerateInvalidXHTMLFromInvalidNesting()
//	{
//		$base = new CryoBB_Base();
//		$base->addTag($this->tagBold());
//		$base->addTag($this->tagItalics());
//		
//		$actual = $base->make('[b]foo[i]bar[/b][/i]');
//		$this->assertEqual($actual, '<strong>foo<i>bar</strong></i>', 'Should generate invalid XHTML from invalid nesting');
//	}
	
	function testShouldAddTagDefinitionsByArray()
	{
		$base = new CryoBB_Base();
		$base->addTags(array($this->tagBold(), $this->tagItalics()));
		
		$actual = $base->make('[b]123abc[/b] [i]foo[/i]');
		$this->assertEqual($actual, '<strong>123abc</strong> <em>foo</em>', 'should add tag definitions by array');
	}
	
	function testShouldAddTagDefinitionsByMagicParamaters()
	{
		$base = new CryoBB_Base();
		$base->addTags($this->tagBold(), $this->tagItalics());
		
		$actual = $base->make('[b]123abc[/b] [i]foo[/i]');
		$this->assertEqual($actual, '<strong>123abc</strong> <em>foo</em>', 'should add tag definitions by "magic PHP Pararmaters"');
	}
	
	function testShouldConvertBBCodeAttributeToHtmlAttribute()
	{
		$base = new CryoBB_Base();
		$base->addTag($this->tagColor());
		
		$actual = $base->make('[color=#FF0000]123abc[/color]');
		$this->assertEqual($actual, '<span style="color: #FF0000;">123abc</span>', 'Should convert BBCode attribute to HTML attribute');
	}
	
	function testShouldUseDefault()
	{
		$base = new CryoBB_Base();
		$base->addTag($this->tagColor());
		
		$actual = $base->make('[color]123abc[/color]');
		$this->assertEqual($actual, '<span style="color: #0000FF;">123abc</span>', 'Should use the value of setOpenTag because attribute is absent');
	}
	
	function testShouldProcessContents()
	{
		$base = new CryoBB_Base();
		$base->addTag($this->tagUpper());
		
		$actual = $base->make('[upper]123abc[/upper]');
		$this->assertEqual($actual, '123ABC', 'Should process tag contents with strtoupper()');
	}
	
	function testShouldReplaceNewlines()
	{
		$base = new CryoBB_Base();
		
		$actual = $base->make("123abc\n456def");
		$this->assertEqual($actual, "123abc<br />\n456def", 'Should replace new lines with the &lt;br&gt; tag');
	}
	
	function testShouldParseParameter()
	{
		$base = new CryoBB_Base();
		$base->addTags($this->tagQuote(), $this->tagItalics());
		
		$actual = $base->make('[quote=[i]123abc[/i] abc123]def456[/quote]');
		$this->assertEqual($actual, '<div><strong><em>123abc</em> abc123 wrote:</strong></div><blockquote>def456</blockquote>', 'Should evaluate the BBCode in the attribute');
	}
	
	function testShouldWorkProperly()
	{
		$base = new CryoBB_Base();
		$base->addTags($this->allTags());
		
		$actual = $base->make('[b]four [i]score [color=#FF0000]and' . "\n" .
			'[code]twenty [i]years [/i]ago, [/code]our [/color]fathers [upper]brought [/upper]forth [/i]on [/b]this...');
		$expected = '<strong>four <em>score <span style="color: #FF0000;">and<br />' . "\n" .
			'<pre class="code">twenty [i]years [/i]ago, </pre>our </span>fathers BROUGHT forth </em>on </strong>this...';
		$this->assertEqual($actual, $expected, 'Should evaluate all BBCode properly');
	}
	
	function allTags()
	{
		$b = $this->tagBold();
		$i = $this->tagItalics();
		$color = $this->tagColor();
		$upper = $this->tagUpper();
		$code = $this->tagCode();
		$quote = $this->tagQuote();		
		return array($b, $i, $color, $upper, $code, $quote);
	}
	
	function tagBold()
	{
		$b = new CryoBB_Tag('b');
		$b->setOpenTag('<strong>');
		$b->setCloseTag('</strong>');
		return $b;
	}
	
	function tagItalics()
	{
		$i = new CryoBB_Tag('i');
		$i->setOpenTag('<em>');
		$i->setCloseTag('</em>');
		return $i;
	}
	
	function tagColor()
	{
		$color = new CryoBB_Tag_Parameter('color');
		$color->setOpenTag('<span style="color: #0000FF;">');
		$color->setOpenTagParameter('<span style="color: {placeholder};">', '{placeholder}');
		$color->setCloseTag('</span>');
		return $color;
	}
	
	function tagUpper()
	{
		$upper = new CryoBB_Tag('upper');
		$upper->setProcessor(new Processor_Upper());
		return $upper;
	}
	
	function tagQuote()
	{
		$quote = new CryoBB_Tag_Parameter('quote');
		$quote->setOpenTag('<div><strong>Quote:</strong></div><blockquote>');
		$quote->setOpenTagParameter('<div><strong>{placeholder} wrote:</strong></div><blockquote>', '{placeholder}');
		$quote->setCloseTag('</blockquote>');
		$quote->parseParameter(true);
		return $quote;
	}
	
	function tagCode()
	{
		$code = new CryoBB_Tag('code');
		$code->parseContents(false);
		$code->setOpenTag('<pre class="code">');
		$code->setCloseTag('</pre>');
		return $code;
	}
}